package com.lxl;

import com.lxl.config.SystemConfig;
import com.lxl.filter.FormatFilter;
import com.lxl.servlet.*;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.deploy.FilterDef;
import org.apache.catalina.deploy.FilterMap;
import org.apache.catalina.startup.Tomcat;

import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class EmbeddedTomcatLauncher {
    private static Connector nioConnector;
    private static StandardContext standardContext;
    private static Tomcat tomcat;
    private static boolean running;

    private static Logger LOGGER;
    static{
        LOGGER = Logger.getLogger(Launcher.class.getName());
        LOGGER.setLevel(Level.INFO);
    }

    public static void startTomcat(){
        try {
            if (!running){
                initWebServer();

                tomcat.start();
                running = true;
                LOGGER.info("The entrance: http://" + Inet4Address.getLocalHost().getHostAddress()
                        + ":" + SystemConfig.SERVER_NIO_PORT
                        + SystemConfig.ETL_CONTEXT_NAME
                        + "/" + "[TASK_NAME]");
                tomcat.getServer().await();
            }
        } catch (LifecycleException e) {
            e.printStackTrace();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static void stopTomcat(){
        try {
            if (running){
                tomcat.stop();
                running = false;
            }
        } catch (LifecycleException e) {
            e.printStackTrace();
        }
    }

    public static boolean isRunning(){
        return running;
    }

    private static void initWebServer() throws LifecycleException, ClassNotFoundException {
        LOGGER.info("Tomcat environment is being initialized.");

        initNioConnector();
        initStandardContext();
        insertFilter();
        initTomcat();
        insertServlet();
    }

    private static void initNioConnector(){
        nioConnector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        nioConnector.setAsyncTimeout(SystemConfig.NIO_CONNECTOR_ASYNC_TIMEOUT);
        nioConnector.setPort(SystemConfig.SERVER_NIO_PORT);
    }

    private static void initStandardContext(){
        standardContext = new StandardContext();
        standardContext.setPath(SystemConfig.ETL_CONTEXT_NAME);
        standardContext.addLifecycleListener(new Tomcat.FixContextListener());
    }

    private static void insertFilter(){

        Class[] filterClazzes = {FormatFilter.class};

        for (Class clazz : filterClazzes){
            FilterDef filterDef = new FilterDef();
            FilterMap filterMap = new FilterMap();

            filterDef.setFilterName(clazz.getSimpleName());
            filterDef.setFilterClass(clazz.getName());

            filterMap.setFilterName(clazz.getSimpleName());
            filterMap.addURLPattern("/*");

            standardContext.addFilterDef(filterDef);
            standardContext.addFilterMap(filterMap);
        }
    }

    private static void initTomcat(){
        tomcat = new Tomcat();
        tomcat.setBaseDir(SystemConfig.SERVER_TEMP_PATH);

        tomcat.getHost().addChild(standardContext);
        tomcat.getService().addConnector(nioConnector);
        tomcat.setConnector(nioConnector);
    }

    private static void insertServlet(){
        tomcat.addServlet(SystemConfig.ETL_CONTEXT_NAME, "testServlet", new TestServlet());
        standardContext.addServletMapping("/test","testServlet");

        tomcat.addServlet(SystemConfig.ETL_CONTEXT_NAME, "shortTranServlet", new ShortTransServlet());
        standardContext.addServletMapping("/shortTrans","shortTranServlet");
        tomcat.addServlet(SystemConfig.ETL_CONTEXT_NAME,"shortJobServlet",new ShortJobServlet());
        standardContext.addServletMapping("/shortJob","shortJobServlet");
        tomcat.addServlet(SystemConfig.ETL_CONTEXT_NAME, "longTranServlet", new LongTransServlet());
        standardContext.addServletMapping("/longTrans","longTranServlet");
        tomcat.addServlet(SystemConfig.ETL_CONTEXT_NAME,"longJobServlet",new LongJobServlet());
        standardContext.addServletMapping("/longJob","longJobServlet");
        tomcat.addServlet(SystemConfig.ETL_CONTEXT_NAME,"uploadServlet",new UploadServlet());
        standardContext.addServletMapping("/upload","uploadServlet");
        tomcat.addServlet(SystemConfig.ETL_CONTEXT_NAME,"deleteServlet",new DeleteServlet());
        standardContext.addServletMapping("/delete","deleteServlet");
    }
}
